﻿using System;
using System.Reflection;
using System.Runtime.Serialization;
namespace CommonLib
{
	public abstract class LazySingleton<T> where T : LazySingleton<T>
	{
		static readonly private Lazy<T> _instance;
		static public T Instance => _instance.Value;

		/// <summary>
		/// Default static constructor initializes Lazy constructor.
		/// </summary>
		static LazySingleton()
		{
			_instance = new Lazy<T>(() =>
			{
				try
				{
					// Binding flags include private constructors.
					var constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
					return (T)constructor.Invoke(null);
				}
				catch (Exception exception)
				{
					throw new SingletonConstructorException(exception);
				}
			});
			//_instance.Value.SingletonInit();
		}
	}

	[Serializable]
	internal class SingletonConstructorException : Exception
	{
		private Exception exception;

		public SingletonConstructorException()
		{
		}

		public SingletonConstructorException(Exception exception)
		{
			this.exception = exception;
		}

		public SingletonConstructorException(string message) : base(message)
		{
		}

		public SingletonConstructorException(string message, Exception innerException) : base(message, innerException)
		{
		}

		protected SingletonConstructorException(SerializationInfo info, StreamingContext context) : base(info, context)
		{
		}
	}
}